package internal

import (
	"buding-ai/internal/core"
	middleware2 "buding-ai/internal/web/middleware"
	"buding-ai/internal/web/router"
	"context"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

// Application 应用程序结构体
type Application struct {
	Engine *gin.Engine
	Server *http.Server
	Logger *log.Logger
}

// Start 启动应用
func (a *Application) Start(addr string) error {
	a.Logger.Printf("服务启动，监听地址: %s", addr)

	// 配置HTTP服务器
	a.Server = &http.Server{
		Addr:           addr,
		Handler:        a.Engine,
		ReadTimeout:    30 * time.Minute,
		WriteTimeout:   30 * time.Minute,
		IdleTimeout:    60 * time.Minute,
		MaxHeaderBytes: 1 << 20, // 1 MB
	}

	// 启动服务器
	return a.Server.ListenAndServe()
}

// Stop 停止应用
func (a *Application) Stop(ctx context.Context) {
	a.Logger.Println("应用程序正在关闭...")

	// 设置超时上下文
	stopCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	// 关闭HTTP服务器
	if a.Server != nil {
		if err := a.Server.Shutdown(stopCtx); err != nil {
			a.Logger.Printf("HTTP服务器关闭错误: %v", err)
		}
	}

	// 关闭MongoDB连接
	core.CloseMongoConnection()

	// 关闭数据库连接
	sqlDB, err := core.DB.DB()
	if err == nil {
		if err := sqlDB.Close(); err != nil {
			a.Logger.Printf("数据库连接关闭错误: %v", err)
		} else {
			a.Logger.Println("数据库连接已关闭")
		}
	}

	a.Logger.Println("应用程序已安全关闭")
}

// NewApplication 创建新的应用实例
func NewApplication() *Application {
	// 设置Gin模式
	gin.SetMode(gin.DebugMode)

	// 创建Logger
	logger := log.New(os.Stdout, "[App] ", log.LstdFlags)

	// 创建Gin引擎
	engine := gin.Default()
	engine.NoRoute(func(c *gin.Context) {
		c.String(http.StatusNotFound, "资源未找到")
	})
	// 跨域
	engine.Use(func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

		// 处理预检请求
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}
		c.Next()
	})
	engine.Use(middleware2.Logger())       // 日志中间件
	engine.Use(middleware2.Recovery())     // 恢复中间件
	engine.Use(middleware2.ErrorHandler()) // 错误处理中间件

	// 设置路由
	router.SetupRouter(engine.Group("/api"))

	app := &Application{
		Engine: engine,
		Logger: logger,
	}

	// 设置信号处理
	go app.handleSignals()

	return app
}

// handleSignals 处理系统信号
func (a *Application) handleSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)

	// 阻塞直到接收到信号
	sig := <-c
	a.Logger.Printf("收到系统信号: %v", sig)

	// 创建上下文并调用Stop方法
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	a.Stop(ctx)

	// 如果不想立即关闭，可以给其他goroutine一些时间来完成
	time.Sleep(100 * time.Millisecond)
	os.Exit(0)
}
